#include "ITM.h"

// DWT init

uint32_t DWT_Init(void)
{

  /* Enable use of DWT */
  if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk))
  {
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  }

  /* Unlock */
  dwt_access(true);

  /* Reset the clock cycle counter value */
  DWT->CYCCNT = 0;

  /* Enable  clock cycle counter */
  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

  /* 3 NO OPERATION instructions */
  __NOP();
  __NOP();
  __NOP();

  /* Check if clock cycle counter has started */
  return (DWT->CYCCNT) ? 0 : 1;
}

void dwt_access(bool ena)
{
#if (__CORTEX_M == 0x07U)
  /*
   * Define DWT LSR mask which is (currentuly) not defined by the CMSIS.
   * Same as ITM LSR one.
   */
#if !defined DWT_LSR_Present_Msk
#define DWT_LSR_Present_Msk ITM_LSR_Present_Msk
#endif
#if !defined DWT_LSR_Access_Msk
#define DWT_LSR_Access_Msk ITM_LSR_Access_Msk
#endif
  uint32_t lsr = DWT->LSR;

  if ((lsr & DWT_LSR_Present_Msk) != 0)
  {
    if (ena)
    {
      if ((lsr & DWT_LSR_Access_Msk) != 0)
      { // locked
        DWT->LAR = 0xC5ACCE55;
      }
    }
    else
    {
      if ((lsr & DWT_LSR_Access_Msk) == 0)
      { // unlocked
        DWT->LAR = 0;
      }
    }
  }
#else  /* __CORTEX_M */
  UNUSED(ena);
#endif /* __CORTEX_M */
}
/**
 * @brief 使用DWT心跳延时Tick
 * @param us 微秒
 * @date 2022-11-15
 */
void DWT_delay_Tick(uint32_t tick)
{
#if defined(DWT_BASE) && !defined(DWT_DELAY_DISABLED)
  int32_t start = DWT_GetTicks();
  while ((int32_t)DWT_GetTicks() - start < tick)
    ;
#endif
}

/**
 * @brief 使用DWT心跳延时微秒
 * @param us 微秒
 * @date 2022-11-15
 */
void DWT_delay_us(uint32_t us)
{
#if defined(DWT_BASE) && !defined(DWT_DELAY_DISABLED)
  int32_t start = DWT_GetTicks();
  int32_t cycles = us * (SystemCoreClock / 1000000);

  while ((int32_t)DWT_GetTicks() - start < cycles)
    ;
#endif
}

/**
 * @brief 使用DWT延时毫秒
 * @param ms 
 * @date 2022-11-15
 */
void DWT_delay_ms(uint32_t ms)
{
  uint32_t old_counter, current_counter;
  uint32_t delay_ms;

  old_counter = DWT_GetTicks();
  current_counter = DWT_GetTicks();
  delay_ms = 0;
  while (delay_ms < ms)
  {
    current_counter = DWT_GetTicks();
    if (current_counter > old_counter)
      delay_ms = (current_counter - old_counter) / (SystemCoreClock / 1000);
    else
      delay_ms = (current_counter + 0XFFFFFFFF - old_counter) / (SystemCoreClock / 1000);
  }
}

/**
 * @brief 使用DWT测量时间
 * @param timedata 
 * @retval float 返回传入变量距离上次记录的时差
 * @note 测量时间最大为 DWT_MAX_USEC(),单位为微秒
 * @date 2022-11-27
 */
float DWT_Time_Measure(uint32_t *old_counter)
{
  uint32_t counter, couter_current;
  couter_current = DWT_GetTicks();
  if (couter_current > *old_counter)
    counter = couter_current - *old_counter;
  else
    counter = couter_current + 0XFFFFFFFF - *old_counter;
  *old_counter = couter_current;
  return DWT_TickToUS(counter);
}

/**
 * @brief 使用DWT测量时间
 * @param timedata 
 * @retval uint32 返回传入变量距离上次记录的时差(Tick)
 * @note 测量时间最大为 uint32_t
 * @date 2024-11-14
 */
inline uint32_t DWT_Time_MeasureTick(uint32_t *old_counter)
{
  uint32_t counter, couter_current;
  couter_current = DWT_GetTicks();
  if (couter_current > *old_counter)
    counter = couter_current - *old_counter;
  else
    counter = couter_current + 0XFFFFFFFF - *old_counter;
  *old_counter = couter_current;
  return counter;
}
